package com.mama100.rpc.mdp.service.finagle;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.mama100.common.finagle.util.FinagleRPC;
import com.mama100.common.finagle.util.RpcUtil;
import com.mama100.rpc.mdp.MdpInoutUtil;
import com.mama100.rpc.mdp.constant.ResponseCode;
import com.mama100.rpc.mdp.thrift.inout.GetOrderReportRequest;
import com.mama100.rpc.mdp.thrift.inout.GetOrderReportResponse;
import com.mama100.rpc.mdp.thrift.inout.common.BaseResponse;
import com.twitter.util.ExecutorServiceFuturePool;
import com.twitter.util.Function0;
import com.twitter.util.Future;

@FinagleRPC
@Service
public class RpcOrderReportService implements com.mama100.rpc.mdp.thrift.OrderReportService.ServiceIface {
	protected Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private ExecutorServiceFuturePool futurePool;

	@Resource(name = "cpmsJdbcTemplate")
	JdbcTemplate jdbcTemplate;

	@Override
	public Future<GetOrderReportResponse> getOrderReport(GetOrderReportRequest req) {
		return futurePool.apply(new Function0<GetOrderReportResponse>() {
			@Override
			public GetOrderReportResponse apply() {

				GetOrderReportResponse resp = MdpInoutUtil.getGetOrderReportResponse(RpcUtil.genSeqNo());
				BaseResponse base = resp.getBaseResp();
				if (req.getBaseReq().getSeqNo() != null) {
					base.setSeqNo(req.getBaseReq().getSeqNo());
				}
				log.info("receive:" + req.toString());
				try {
					String startTime = req.getStartTime();
					String endTime = req.getEndTime();
					String terminalCode = req.getTerminalCode();

					String sourceSystem = req.getSourceSystem();

					if (startTime == null || endTime == null) {
						base.setRespCode(ResponseCode.INVALID_REQUEST.getCode());
						base.setRespDesc("startTime endTime 不能为空!");
						log.info("return:" + resp);
						return resp;
					}
					if (terminalCode == null) {
						base.setRespCode(ResponseCode.INVALID_REQUEST.getCode());
						base.setRespDesc("terminalCode 不能为空!");
						log.info("return:" + resp);
						return resp;
					}

					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					Date startDate = sdf.parse(startTime);
					Date endDate = sdf.parse(endTime);
					endDate=new Date(endDate.getTime()+24*60*60*1000);
					
					//String sql = "select sum(ORDERBALANCE) as ORDERBALANCE  ,sum(ORDERCOUNT) as ORDERCOUNT ,sum(ORDERPOINT) as ORDERPOINT, count(distinct CUSTOMER_ID) as ORDERCUSTOMER from mama100_edw.mdp_order_detail_view  where  COUNT_TIME >= ?  and  COUNT_TIME <=  ?  and TERMINAL_CODE = ? ";
					String sql = getOrderDetailSql(sourceSystem);
					Map<String, Object> map = null;
					if (sourceSystem == null) {
						map = jdbcTemplate.queryForMap(sql, startDate, endDate, terminalCode);
					} else {
						sql += " and SOURCESYSTEM=?  ";
						map = jdbcTemplate.queryForMap(sql, startDate, endDate, terminalCode, sourceSystem);
					}
					
					
					
					 
					double allPoint =jdbcTemplate.queryForObject("select /*+index(t,EDW_DTS_CUST_PRODUCT_POINT_I4 )*/ nvl(sum(t.product_point),0) as product_point from mama100_edw.edw_dts_cust_product_point t where  t.created_time >= to_date('"+startTime+"','yyyy-mm-dd')  and  t.created_time <= to_date('"+endTime+"','yyyy-mm-dd') and  t.terminal_code  = '"+terminalCode+"' and t.status in (1,11) ", Double.class);
					//double allPoint = map.get("ALLPOINTS") == null ? 0 : ((BigDecimal) map.get("ALLPOINTS")).doubleValue();
					
					// 判断 map.get 因为select sum 有可能是 null
					double orderBalance = map.get("ORDERBALANCE") == null ? 0 : ((BigDecimal) map.get("ORDERBALANCE")).doubleValue();
					double orderCount = map.get("ORDERCOUNT") == null ? 0 : ((BigDecimal) map.get("ORDERCOUNT")).doubleValue();
					double orderPoint = map.get("ORDERPOINT") == null ? 0: ((BigDecimal) map.get("ORDERPOINT")).doubleValue();
					double orderCustomer = map.get("ORDERCUSTOMER") == null ?0 : ((BigDecimal) map.get("ORDERCUSTOMER")).doubleValue();
					

					double customerBalance = orderCount == 0 ? 0 : new BigDecimal(orderBalance / orderCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
					double customerPoint=orderCount == 0 ? 0 : new BigDecimal(((double) orderPoint) / orderCount).setScale(2,RoundingMode.HALF_UP).doubleValue();
					double crderPointPer = allPoint == 0 ? 0 : new BigDecimal(orderPoint / allPoint).setScale(4, RoundingMode.HALF_UP).doubleValue();
					//保留四位小数
					DecimalFormat df = new DecimalFormat("######0.0000"); 
					String crderPointPerStr = df.format(crderPointPer);
					crderPointPer = Double.valueOf(crderPointPerStr);
					
					resp.setOrderBalance(orderBalance);
					resp.setOrderCount((int)orderCount);
					resp.setOrderPoint((int)orderPoint);
					resp.setOrderCustomer((int)orderCustomer);
					resp.setOrderCustomerBalance(customerBalance);
					resp.setOrderCustomerPoint(customerPoint);
					resp.setOrderPointPer(crderPointPer);

				} catch (Exception e) {
					log.error("error:", e);
					base.setRespCode(ResponseCode.SERVER_ERROR.getCode());
					base.setRespDesc(ResponseCode.SERVER_ERROR.getDesc());
					log.info("return:" + resp);
					return resp;
				}
				base.setRespCode(ResponseCode.SUCCESS.getCode());
				base.setRespDesc(ResponseCode.SUCCESS.getDesc());
				log.info("return:" + resp.toString());
				return resp;
			}

		});
	}
	
	private String getOrderDetailSql(String sourceSystem){
		StringBuffer sb = new StringBuffer();
		sb.append(" select ");
		sb.append(" sum(ORDERBALANCE) as ORDERBALANCE, ");
		sb.append(" sum(ORDERCOUNT) as ORDERCOUNT, ");
		sb.append(" sum(ORDERPOINT) as ORDERPOINT, ");
		sb.append(" count(distinct CUSTOMER_ID) as ORDERCUSTOMER ");
		sb.append(" from ( ");
		
		sb.append(" select ");
		sb.append(" a.count_time, ");
		sb.append(" a.system_code as sourcesystem, ");
		sb.append(" a.terminal_code, ");
		sb.append(" a.customer_id, ");
		sb.append(" price as orderbalance, ");
		sb.append(" orders as  ordercount, "); //积分笔数
		sb.append(" points as orderpoint ");  //积分分值
		//sb.append(" sum(custs) as ordercustomer, ");
		//sb.append(" decode(sum(orders),0,0,sum(points)/sum(orders)) as ordercustomerpoint, "); //客单积分
		//sb.append(" decode(sum(orders),0,0,sum(pays)/sum(orders)) as ordercustomerbalance, "); //客单金额
		//sb.append(" product_point as allpoints ");  //O2O订单积分占比
		sb.append(" from ( ");
		
		sb.append(" select ");
		sb.append(" to_char(point_time,'yyyy-mm-dd') count_time, ");
		sb.append(" system_code, ");
		sb.append(" terminal_code, ");
		sb.append(" customer_id, ");
		sb.append(" sum(order_price) as price, ");
		sb.append(" count(distinct order_id) as orders, ");
		sb.append(" sum(case when pay_status<>0 then pay_price else 0 end ) as pays, ");
		sb.append(" sum(point_total) as points ");
		sb.append(" from mama100_cpms.opt_o2o_order_detail h ");
		
		sb.append("  where h.point_time >= ? ");
		sb.append("  and h.point_time <= ? ");
		sb.append("  and h.terminal_code = ? ");
		if(sourceSystem != null){
			sb.append("  and h.system_code = ? ");
		}
		sb.append(" and h.order_id is not null ");  //O2O线上销售
		sb.append(" and h.business_type ='O2O线上销售' "); //o2o下次版本会新增其他的业务类型，需要这个条件过滤
		sb.append(" group by to_char(point_time,'yyyy-mm-dd'),system_code,terminal_code,customer_id ");
		
		sb.append(" ) a ");
		sb.append(" group by a.count_time,a.system_code,a.terminal_code,a.customer_id,price,orders,points ");
		sb.append(" ) ");
		//System.out.println(sb.toString());
		return sb.toString();
	}
}
